#!/usr/bin/env python
# Team 4067 64-bit Java Disable Tool - Disable 64-bit Java to enable SmartDashboard to run!
# Copyright (C) 2013 River Hill HS Robotics Team (Albert H.)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import os
import sys
import shutil
import traceback
import ctypes

try:
	import win32com.shell.shell as shell
except:
	print "ERROR: You need to install pywin32 in order to use this program."
	print "Get it at http://sourceforge.net/projects/pywin32/ and install it."
	print "Press ENTER to exit."
	raw_input()
	sys.exit(1)

# Functions

# Windows 64-bit check - courtesy of "phobie" from http://stackoverflow.com/a/12578715
def is_windows_64bit():
    if 'PROCESSOR_ARCHITEW6432' in os.environ:
        return True
    return os.environ['PROCESSOR_ARCHITECTURE'].endswith('64')

def selfElevate():
	script = os.path.abspath(sys.argv[0])
	params = ' '.join([script] + sys.argv[1:])
	try:
		# nShow = SW_SHOW = 5
		shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params, nShow=5)
	except Exception, e:
		print "Looks like you canceled the elevation request. You must elevate to run this"
		print "script."
		print "Detailed Python error:"
		print traceback.format_exc()
		print "Press ENTER to exit."
		raw_input()
		sys.exit(1)
	sys.exit(0)

def IOFail():
	# Check for elevation
	if ctypes.windll.shell32.IsUserAnAdmin() == 1:
		print "ERROR: Failed to move file! Please check that you have permissions to move the file, then try again."
		print "Press ENTER to exit."
		raw_input()
		sys.exit(1)
	else:
		print "Re-running with more privledges..."
		selfElevate()
		sys.exit(0)

print "64-bit Java Disable Tool"
print "========================="
print "Copyright (C) 2013 River Hill High School Robotics Team (Albert H.)"
print "              *** FRC 4067 The Incredible Hawk *** "
print ""
# Sanity check - is this Windows?
if sys.platform != 'win32':
	print "ERROR: This tool only runs on Windows."
	print "Press ENTER to exit."
	raw_input()
	sys.exit(1)

if not is_windows_64bit():
	print "ERROR: This tool only runs on Windows 64-bit. (You are running Windows 32-bit, as detected by this program.)"
	print "Press ENTER to exit."
	raw_input()
	sys.exit(1)

# Get the system paths
WINDOWS_DIR = os.environ.get("SYSTEMROOT")
USER_DIR = os.environ.get("USERPROFILE")

if os.path.exists(os.path.join(USER_DIR, "My Documents")):
	# Windows NT, 2000, XP
	USER_DOC_DIR = os.path.join(USER_DIR, "My Documents")
elif os.path.exists(os.path.join(USER_DIR, "Documents")):
	# Windows Vista, 7, 8
	USER_DOC_DIR = os.path.join(USER_DIR, "Documents")
else:
	print "ERROR: Couldn't find your documents directory! This is a weird bug unless you modified this program!"
	print "Press ENTER to exit."
	raw_input()
	sys.exit(1)

USER_DOCB_DIR = os.path.join(USER_DOC_DIR, "Java64Backup")
if not os.path.exists(USER_DOCB_DIR):
	print "Creating backup directory for the first time..."
	os.makedirs(USER_DOCB_DIR)

# Another sanity check - does WINDOWS_DIR exist?
if (not WINDOWS_DIR) or (not os.path.exists(WINDOWS_DIR)):
	print "ERROR: Couldn't find the Windows directory! This is a weird bug unless you modified this program!"
	print "Press ENTER to exit."
	raw_input()
	sys.exit(1)

# Last sanity check - does SYSWOW64 exist?
if not os.path.exists(os.path.join(WINDOWS_DIR, "SYSWOW64")):
	print "ERROR: Couldn't find the Windows 64-bit system directory! This is a weird bug unless you modified this program!"
	print "Press ENTER to exit."
	raw_input()
	sys.exit(1)

WINDOWS_SYS64_DIR = os.path.join(WINDOWS_DIR, "SYSWOW64")
WINDOWS_SYS32_DIR = os.path.join(WINDOWS_DIR, "SYSTEM32")

# Now start doing things!
JAVA_SYS64_PATH = os.path.join(WINDOWS_SYS64_DIR, "java.exe")
JAVAW_SYS64_PATH = os.path.join(WINDOWS_SYS64_DIR, "javaw.exe")
JAVAWS_SYS64_PATH = os.path.join(WINDOWS_SYS64_DIR, "javaws.exe")

JAVA_SYS32_PATH = os.path.join(WINDOWS_SYS32_DIR, "java.exe")
JAVAW_SYS32_PATH = os.path.join(WINDOWS_SYS32_DIR, "javaw.exe")
JAVAWS_SYS32_PATH = os.path.join(WINDOWS_SYS32_DIR, "javaws.exe")

JAVA_USERDOCB_PATH = os.path.join(USER_DOCB_DIR, "java.exe")
JAVAW_USERDOCB_PATH = os.path.join(USER_DOCB_DIR, "javaw.exe")
JAVAWS_USERDOCB_PATH = os.path.join(USER_DOCB_DIR, "javaws.exe")

JAVA_IN_SYS64 = os.path.exists(JAVA_SYS64_PATH)
JAVAW_IN_SYS64 = os.path.exists(JAVAW_SYS64_PATH)
JAVAWS_IN_SYS64 = os.path.exists(JAVAWS_SYS64_PATH)

JAVA_IN_SYS32 = os.path.exists(JAVA_SYS32_PATH)
JAVAW_IN_SYS32 = os.path.exists(JAVAW_SYS32_PATH)
JAVAWS_IN_SYS32 = os.path.exists(JAVAWS_SYS32_PATH)

JAVA_IN_USERDOC = os.path.exists(JAVA_USERDOCB_PATH)
JAVAW_IN_USERDOC = os.path.exists(JAVAW_USERDOCB_PATH)
JAVAWS_IN_USERDOC = os.path.exists(JAVAWS_USERDOCB_PATH)

if ctypes.windll.shell32.IsUserAnAdmin() == 0:
	print "This program needs elevation. Elevating..."
	selfElevate()
else:
	print "Detected admin privledges."

if JAVA_IN_SYS64 and JAVAW_IN_SYS64 and JAVAWS_IN_SYS64 and JAVA_IN_SYS32 and JAVAW_IN_SYS32 and JAVAWS_IN_SYS32:
	print "Detected Java 64-bit installation in system directory, moving all into a backup folder."
	try:
		print "Copying file: "+JAVA_SYS64_PATH
		shutil.copy(JAVA_SYS64_PATH, JAVA_USERDOCB_PATH)
		print "Copying file: "+JAVAW_SYS64_PATH
		shutil.copy(JAVAW_SYS64_PATH, JAVAW_USERDOCB_PATH)
		print "Copying file: "+JAVAWS_SYS64_PATH
		shutil.copy(JAVAWS_SYS64_PATH, JAVAWS_USERDOCB_PATH)
		print "Copying file: "+JAVA_SYS32_PATH
		shutil.copy(JAVA_SYS32_PATH, JAVA_USERDOCB_PATH)
		print "Copying file: "+JAVAW_SYS32_PATH
		shutil.copy(JAVAW_SYS32_PATH, JAVAW_USERDOCB_PATH)
		print "Copying file: "+JAVAWS_SYS32_PATH
		shutil.copy(JAVAWS_SYS32_PATH, JAVAWS_USERDOCB_PATH)
		print "Removing file: "+JAVA_SYS64_PATH
		os.remove(JAVA_SYS64_PATH)
		print "Removing file: "+JAVAW_SYS64_PATH
		os.remove(JAVAW_SYS64_PATH)
		print "Removing file: "+JAVAWS_SYS64_PATH
		os.remove(JAVAWS_SYS64_PATH)
		print "Removing file: "+JAVA_SYS32_PATH
		os.remove(JAVA_SYS32_PATH)
		print "Removing file: "+JAVAW_SYS32_PATH
		os.remove(JAVAW_SYS32_PATH)
		print "Removing file: "+JAVAWS_SYS32_PATH
		os.remove(JAVAWS_SYS32_PATH)
	except IOError:
		IOFail()
	except WindowsError:
		IOFail()
	except Exception, e:
		print "ERROR: Something weird happened. Please report this error to the developer!"
		print "Python error details follow:"
		print traceback.format_exc()
		print "Copy and paste the error by right clicking either in the console or on the"
		print "title bar of the console! You need to click Mark, then select the above error,"
		print "and then bring up the menu and select Copy."
		print ""
		print "Press ENTER to exit."
		raw_input()
		sys.exit(1)
elif (not JAVA_IN_SYS64 and not JAVAW_IN_SYS64 and not JAVAWS_IN_SYS64) and (JAVA_IN_USERDOC and JAVAW_IN_USERDOC and JAVAWS_IN_USERDOC):
	print "Detected Java 64-bit installation in backup folder, moving back to system directory."
	try:
		print "Moving file: "+JAVA_USERDOCB_PATH
		shutil.copy(JAVA_USERDOCB_PATH, JAVA_SYS64_PATH)
		shutil.move(JAVA_USERDOCB_PATH, JAVA_SYS32_PATH)
		print "Moving file: "+JAVAW_USERDOCB_PATH
		shutil.copy(JAVAW_USERDOCB_PATH, JAVAW_SYS64_PATH)
		shutil.move(JAVAW_USERDOCB_PATH, JAVAW_SYS32_PATH)
		print "Moving file: "+JAVAWS_USERDOCB_PATH
		shutil.copy(JAVAWS_USERDOCB_PATH, JAVAWS_SYS64_PATH)
		shutil.move(JAVAWS_USERDOCB_PATH, JAVAWS_SYS32_PATH)
	except IOError:
		IOFail()
	except WindowsError:
		IOFail()
	except Exception, e:
		print "ERROR: Something weird happened. Please report this error to the developer!"
		print "Python error details follow:"
		print traceback.format_exc()
		print "Copy and paste the error by right clicking either in the console or on the"
		print "title bar of the console! You need to click Mark, then select the above error,"
		print "and then bring up the menu and select Copy."
		print ""
		print "Press ENTER to exit."
		raw_input()
		sys.exit(1)
else:
	sys.stdout.write("Inconsistent backup detected! Would you like to try and recover? [y/n] ")
	yn = raw_input()
	if yn.lower() == 'y':
		print "Trying to recover..."
		print " - Copying all current system Java executables to the backup directory..."
		try:
			print "  = Copying file: "+JAVA_SYS64_PATH
			shutil.copy(JAVA_SYS64_PATH, JAVA_USERDOCB_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			print "  = (Continuing anyway.)"
		try:
			print "  = Copying file: "+JAVAW_SYS64_PATH
			shutil.copy(JAVAW_SYS64_PATH, JAVAW_USERDOCB_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			print "  = (Continuing anyway.)"
		try:
			print "  = Copying file: "+JAVAWS_SYS64_PATH
			shutil.copy(JAVAWS_SYS64_PATH, JAVAWS_USERDOCB_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			print "  = (Continuing anyway.)"
		try:
			print "  = Copying file: "+JAVA_SYS32_PATH
			shutil.copy(JAVA_SYS32_PATH, JAVA_USERDOCB_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			print "  = (Continuing anyway.)"
		try:
			print "  = Copying file: "+JAVAW_SYS32_PATH
			shutil.copy(JAVAW_SYS32_PATH, JAVAW_USERDOCB_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			print "  = (Continuing anyway.)"
		try:
			print "  = Copying file: "+JAVAWS_SYS32_PATH
			shutil.copy(JAVAWS_SYS32_PATH, JAVAWS_USERDOCB_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			print "  = (Continuing anyway.)"
		
		print " - Moving backup files back to the system directory..."
		
		try:
			print "  = Moving file: "+JAVA_USERDOCB_PATH
			shutil.copy(JAVA_USERDOCB_PATH, JAVA_SYS64_PATH)
			shutil.move(JAVA_USERDOCB_PATH, JAVA_SYS32_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			if os.path.exists(JAVA_SYS64_PATH):
				print "  = (However, this program does exist in the system directory - as long as you haven't changed versions, this should be fine.)"
			print "  = (Continuing anyway.)"
		
		try:
			print "  = Moving file: "+JAVAW_USERDOCB_PATH
			shutil.copy(JAVAW_USERDOCB_PATH, JAVAW_SYS64_PATH)
			shutil.move(JAVAW_USERDOCB_PATH, JAVAW_SYS32_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			if os.path.exists(JAVAW_SYS64_PATH):
				print "  = (However, this program does exist in the system directory - as long as you haven't changed versions, this should be fine.)"
			print "  = (Continuing anyway.)"
		
		try:
			print "  = Moving file: "+JAVAWS_USERDOCB_PATH
			shutil.copy(JAVAWS_USERDOCB_PATH, JAVAWS_SYS64_PATH)
			shutil.move(JAVAWS_USERDOCB_PATH, JAVAW_SYS32_PATH)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			if os.path.exists(JAVAWS_SYS64_PATH):
				print "  = (However, this program does exist in the system directory - as long as you haven't changed versions, this should be fine.)"
		
		print " - Removing backup directory..."
		try:
			shutil.rmtree(USER_DOCB_DIR)
		except Exception, e:
			print "  = FAILED! Python error details follow:"
			print traceback.format_exc()
			print "  = You should try to remove this directory before running this tool again!"
print "Press ENTER to exit."
raw_input()